
import crypto from 'crypto';
import request from 'request';
import uuid from 'uuid';
import moment from 'moment';
import { insertTable, exesql } from '../database/db';
import { sendLogToEmail } from './logger';

const TIMEOUT = 20000;
const KEY_PERFIX = 'key_';
const SECRET_PERFIX = 'secret_';
var baiduProductMap = new Map();

initBiaduProducts();

// 初始化百度产品
async function initBiaduProducts() {
    const sql = 'SELECT `uuid_head`,`api_key`,`api_secret` FROM `baidu_product`;';
    try {
        const { err, result } = await exesql(sql, []);
        if (err) {
            sendLogToEmail(err);
            return;
        }
        baiduProductMap.clear();
        result.forEach(item => {
            baiduProductMap.set(KEY_PERFIX + item.uuid_head, item.api_key);
            baiduProductMap.set(SECRET_PERFIX + item.uuid_head, item.api_secret);
        });
    } catch (error) {
        console.log("加载百度产品失败:" + error.stack);
        sendLogToEmail(error);
    }
}

function randomString() {
    let id = uuid.v1();
    id = id.replace(/-/g, "");
    return id;
}

function insertBaiduLog(uuid, command, input, output, startTime, endTime) {
    const post = {
        uuid: uuid,
        command: command,
        input: JSON.stringify(input),
        output: JSON.stringify(output),
        start_time: startTime,
        end_time: endTime
    }
    insertTable(post, 'baidu_api_log').then(function (data) {
        if (data.err) {
            console.log(data);
        }
    });
}

// 签名
function getSignature(uri, baiduAccessToken, baiduApikey, baiduApiSecret) {
    console.info(`baiduApikey:${baiduApikey}, ${baiduApiSecret}`);
    let nonce = randomString()
    let sha1 = crypto.createHash('sha1');
    sha1.update(nonce)
    sha1.update(baiduApikey)
    sha1.update(baiduApiSecret)
    sha1.update(baiduAccessToken)
    sha1.update(uri)

    let signaturestr = sha1.digest('hex');
    signaturestr = nonce + ':' + signaturestr;
    return signaturestr;
}


// 构建Get请求
function baiduGetOptions(path, baiduAccessToken, deviceUuid) {

    const uuidHead = deviceUuid.substring(0, 4);
    const baiduApikey = baiduProductMap.get(KEY_PERFIX + uuidHead);
    const baiduApiSecret = baiduProductMap.get(SECRET_PERFIX + uuidHead);

    let signString = '';
    try {
        signString = getSignature(path, baiduAccessToken, baiduApikey, baiduApiSecret)
    } catch (error) {
        const errMsg = `baiduGetOptions -> deviceUuid:${deviceUuid},baiduAccessToken:${baiduAccessToken}, baiduApikey:${baiduApikey}, baiduApiSecret:${baiduApiSecret},path:${path},err;${error.stack}`;
        console.log(errMsg);
        sendLogToEmail(errMsg);
    } finally {
        return {
            headers: {
                'X-IOT-APP': baiduApikey,
                'X-IOT-Signature': signString,
                'X-IOT-Signature-Type': 'Web',
                'X-IOT-Token': baiduAccessToken
            },
            uri: 'https://openapi-iot.baidu.com' + path,
            method: 'GET',
            timeout: TIMEOUT,
        };
    }
}

// 构建Post请求
function baiduPostOptions(path, data, baiduAccessToken, deviceUuid) {

    const uuidHead = deviceUuid.substring(0, 4);
    const baiduApikey = baiduProductMap.get(KEY_PERFIX + uuidHead);
    const baiduApiSecret = baiduProductMap.get(SECRET_PERFIX + uuidHead);

    let signString = '';
    try {
        signString = getSignature(path, baiduAccessToken, baiduApikey, baiduApiSecret);
    } catch (error) {
        const errMsg = `baiduGetOptions -> deviceUuid:${deviceUuid},baiduAccessToken:${baiduAccessToken}, baiduApikey:${baiduApikey}, baiduApiSecret:${baiduApiSecret},path:${path},data:${JSON.stringify(data)}`;
        console.log(errMsg);
        sendLogToEmail(errMsg);
    } finally {
        return {
            headers: {
                "Connection": "close",
                'X-IOT-APP': baiduApikey,
                'X-IOT-Signature': signString,
                'X-IOT-Signature-Type': 'Web',
                'X-IOT-Token': baiduAccessToken
            },
            url: 'https://openapi-iot.baidu.com' + path,
            method: 'POST',
            json: true,
            timeout: TIMEOUT,
            body: data
        };
    }
}

/**
 * 发送https请求
 */
function sendHttp(options, needSave, uuid) {
    return new Promise(function (resolve, _reject) {
        const startTime = moment(new Date()).format('YYYY-MM-DD HH:mm:ss.SSS');
        request(options, function (error, _response, data) {
            let json = data;
            if (error) {
                json = error + '>>>> \n ' + data + '>>> \n' + JSON.stringify(options);
            }
            if (needSave) {
                const endTime = moment(new Date()).format('YYYY-MM-DD HH:mm:ss.SSS');
                insertBaiduLog(uuid, options.url || options.uri, options, json, startTime, endTime);
            }
            resolve({ err: error, result: json });
        });
    })
}

// 播放状态转换
function actionToString(action) {
    switch (action) {
        case 1:
            return 'NEXT';
        case 2:
            return 'PREVIOUS';
        case 3:
            return 'PLAY_PAUSE';
        default:
            console.error('Unknown action');
            return '';
    }
}


export function baidu_api_get(path, token) {
    const options = baiduGetOptions(path, token, '');
    return sendHttp(options, false, '');
}

export function baidu_api_post(path, body, token) {
    const options = baiduPostOptions(path, body, token, '');
    return sendHttp(options, false, '');
}


// 控制设备
export function controlPlay(deviceUuid, action, token) {
    let path = '/v2/audio/control?deviceUuid=' + deviceUuid + '&action=' + actionToString(action)
    const options = baiduGetOptions(path, token, deviceUuid);
    return sendHttp(options, true, deviceUuid);
}

// 播放音频
export function playBaiduAudio(deviceUuid, albumId, trackId, token) {
    let path = '/v2/audio/play?albumid=' + albumId + '&trackid=' + trackId + '&deviceUuid=' + deviceUuid
    const options = baiduGetOptions(path, token, deviceUuid);
    return sendHttp(options, true, deviceUuid);
}

// 获取播放列表
export function getPlayList(deviceUuid, token) {
    let path = '/v2/audio/playlist?deviceUuid=' + deviceUuid;
    const options = baiduGetOptions(path, token, deviceUuid);
    return sendHttp(options, false, deviceUuid);
}

// 绑定设备
export function bindDeviceToBaidu(deviceUuid, bindToken, baiduToken) {
    let path = '/v2/device/bind';
    const body = {
        deviceUuid: deviceUuid,
        token: bindToken
    };
    const options = baiduPostOptions(path, body, baiduToken, deviceUuid);
    return sendHttp(options, true, deviceUuid);
}

// 获取设备版本
export function getDevcieVersion(deviceUuid, token) {
    let path = '/v2/device/ota/new_version?deviceUuid=' + deviceUuid;
    const options = baiduGetOptions(path, token, deviceUuid);
    return sendHttp(options, false, deviceUuid);
}

// 升级设备
export function upgradeDevice(deviceUuid, packageId, _strategyId, token) {
    let path = '/v2/device/ota/update'
    let postData = {
        deviceUuid: deviceUuid,
        packageId: String(packageId),
    };
    const options = baiduPostOptions(path, postData, token, deviceUuid);
    return sendHttp(options, true, deviceUuid);
}

// 检查升级状态
export function upgradeStatus(deviceUuid, token) {
    let path = '/v2/device/ota/update/status?deviceUuid=' + deviceUuid;
    const options = baiduGetOptions(path, token, deviceUuid);
    return sendHttp(options, false, deviceUuid);
}

// 获取音频信息
export function getTrack(deviceUuid, track_id, token) {
    const path = '/v2/audio/track?trackid=' + track_id;
    const options = baiduGetOptions(path, token, deviceUuid);
    return sendHttp(options, false, deviceUuid);
}

// 自定义控制设备指令
export function control(deviceUuid, data, token) {
    let path = '/v2/device/control/send';
    const postData = {
        deviceUuid: deviceUuid,
        method: 'PUT',
        name: 'play',
        content: JSON.stringify(data)
    };
    const options = baiduPostOptions(path, postData, token, deviceUuid);
    return sendHttp(options, true, deviceUuid);
}

// 搜索专辑
export function searchAlbum(deviceUuid, tags, keywords, page, pSize, token) {
    let path = '/v2/audio/searchalbum?tags='+tags+'&keywords=' + keywords + '&orderby=asc&page=' + page + '&psize=' + pSize;
    path = encodeURI(path);
    const options = baiduGetOptions(path, token, deviceUuid);
    return sendHttp(options, false, '');
}

// 搜索音频
export function searchAudio(deviceUuid,tags, keywords, page, pSize, token) {
    let path = '/v2/audio/searchtrack?tags='+tags+'&keywords=' + keywords + '&orderby=asc&page=' + page + '&psize=' + pSize
    path = encodeURI(path);
    const options = baiduGetOptions(path, token, deviceUuid);
    return sendHttp(options, false, '');
}

// 分页获取专辑中的音频
export function getTracklist(deviceUuid, albumid, page, psize, latestUpid, token) {
    let path = '/v2/audio/tracklist?albumid=' + albumid + '&orderby=asc&page=' + page + '&psize=' + psize + '&upid=' + latestUpid + '&deviceUuid=' + deviceUuid;
    path = encodeURI(path);
    console.log(`path:${path}`);
    let options = baiduGetOptions(path, token, deviceUuid);
    return sendHttp(options, false, '');
}

export function deivceUnbind(deviceUuid, token) {
    let path = '/v2/device/unbind';
    const postData = {
        deviceUuid: deviceUuid
    };
    const options = baiduPostOptions(path, postData, token, deviceUuid);
    return sendHttp(options, false, deviceUuid);
}

// 获取最新升级版本
export function getNewVersion(deviceUuid, token) {
    let path = '/v2/device/ota/new_version?deviceUuid=' + deviceUuid;
    const options = baiduGetOptions(path, token, deviceUuid);
    return sendHttp(options, false, deviceUuid);
}

// 获取设备的当前版本
export function getVersion(deviceUuid, token) {
    let path = '/v2/device/info/by_uuid?deviceUuid=' + deviceUuid;
    const options = baiduGetOptions(path, token, deviceUuid);
    return sendHttp(options, false, deviceUuid);
}

/**
 * 自定义音频播放列表
 * @param {设备uuid} deviceUuid 
 * @param {百度请求token} token 
 * @param {收藏类别} category_id 
 * @param {上一次播放的音频id} latestAudioId 
 */
export function audioCustomPlay(deviceUuid, token, category_id,latestAudioId) {
    const HOST = 'test.aidoor.net';
    const playListUrl = 'https://'+HOST+'/web_api/custom_play_list?deviceUuid='+deviceUuid + '&category_id='+category_id + '&audio_id='+latestAudioId;
    console.log(`playListUrl:${playListUrl}`);
    const path = encodeURI('/v2/audio/custom/play?url='+encodeURIComponent(playListUrl) + '&deviceUuid='+deviceUuid);
    const options = baiduGetOptions(path, token, deviceUuid);
    console.log(options);
    return sendHttp(options, true, deviceUuid);
}










